﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using VitCode.Castle.Entities;

namespace VitCode.Castle.DataAccess
{
    /// <summary>
    /// 通用的自定義上下文物件
    /// </summary>
    public class GenericContext
    {
      
        /// <summary>
        /// Web應用中Context保存的鍵值
        /// </summary>
        private const string ContextKey = "nhibernate.current_session";

        /// <summary>
        /// 標識當前應用是否為Web應用
        /// </summary>
        private static readonly bool m_IsWeb = CheckWhetherIsWeb();

        /// <summary>
        /// 用於Windows應用的線程級上下文成員容器
        /// </summary>
        [ThreadStatic]
        private static NameBasedDictionary _threadCache;

        /// <summary>
        /// 對於Web應用，如果HttpContext對應內容元素沒有初始化，則放置一個空容器
        /// 對於Windows應用，由於threadCache為[ThreadStatic]，無需該過程
        /// </summary>
        public GenericContext()
        {
              
            if (m_IsWeb && (HttpContext.Current.Items[ContextKey] == null))
                HttpContext.Current.Items[ContextKey] = new NameBasedDictionary();
        }

        private static string GetCurrValue(string loginKeyVal,HttpRequest request)
        {
            string reVal = "";
            if(string.IsNullOrEmpty(loginKeyVal))
                return reVal;
            if (reVal != null && reVal.Length == 0 && HttpContext.Current != null && HttpContext.Current.Items != null)
            {
                object reObj = HttpContext.Current.Items[loginKeyVal];
                if (reObj == null)
                {
                    if (HttpContext.Current.Session[loginKeyVal] != null)
                        reObj = HttpContext.Current.Session[loginKeyVal];
                }
                if (reObj != null)
                    reVal = reObj.ToString();

            }
            return reVal;
        }

        private static object GetCurrValue(string loginKeyVal)
        {
            object reVal;
            reVal = GetCurrValue(loginKeyVal, HttpContext.Current.Request);
            if (reVal != null && HttpContext.Current != null)
            {
                object reObj = HttpContext.Current.Items[loginKeyVal];
                if (reObj == null)
                {
                    if (HttpContext.Current.Session[loginKeyVal] != null)
                        reObj = HttpContext.Current.Session[loginKeyVal];
                }
                if (reObj != null)
                    reVal = reObj;
            }
            return reVal;
        }

        public static void SetCurrValueByRequestFromPage(Page page)
        {
            SetCurrValue(PRO_CURR_USER_CODE, GetCurrValue(PRO_CURR_USER_CODE, page.Request));
            SetCurrValue(PRO_CURR_USER_ID, GetCurrValue(PRO_CURR_USER_ID, page.Request));
            SetCurrValue(PRO_CURR_USER_NAME, GetCurrValue(PRO_CURR_USER_NAME, page.Request));
        }

        private static void SetCurrValue(string strKey,object val)
        {
            HttpContext.Current.Items[strKey] = val;
            HttpContext.Current.Session[strKey] = val;
        }

        private const string PRO_CURR_USER_CODE = "PRO_CurrUserCode";
        public static string CurrUserCode
        {
            get
            {
                return GetCurrValue(PRO_CURR_USER_CODE) == null ? "":GetCurrValue(PRO_CURR_USER_CODE).ToString();
            }
            set
            {
                SetCurrValue(PRO_CURR_USER_CODE,value);
            }
        }
        

        private const string PRO_CURR_USER_ID = "PRO_CurrUserId";
        public static Guid CurrUserId
        {
            get
            {
                string strId = GetCurrValue(PRO_CURR_USER_ID) == null ? "" : GetCurrValue(PRO_CURR_USER_ID).ToString();
                if (strId == null || strId.Length != 36)
                    strId = Guid.Empty.ToString();
                return new Guid(strId);
            }
            set
            {
                SetCurrValue(PRO_CURR_USER_ID, value.ToString());
            }
        }

        private const string PRO_CURR_USER = "PRO_CurrUser";
        public static User CurrUser
        {
            get
            {
                var obj = GetCurrValue(PRO_CURR_USER);
                if (obj != null && obj is User)
                    return ((User) obj);
                return null;
            }
            set
            {
                SetCurrValue(PRO_CURR_USER, value);
            }
        }

        private const string PRO_CURR_USER_NAME = "PRO_CurrUserName";
        public static string CurrUserName
        {
            get
            {
                return GetCurrValue(PRO_CURR_USER_NAME) == null ? "" : GetCurrValue(PRO_CURR_USER_NAME).ToString();
            }
            set
            {
                SetCurrValue(PRO_CURR_USER_NAME, value);
            }
        }

        private const string PRO_User_Roles_String = "PRO_UserRolesString";
        public static string UserRolesString
        {
            get
            {
                return GetCurrValue(PRO_User_Roles_String) == null ? "" : GetCurrValue(PRO_User_Roles_String).ToString();
            }
            set
            {
                SetCurrValue(PRO_User_Roles_String, value);
            }
        }



        /// <summary>
        /// 獲取當前的系統用戶(是一個資料提取過程)
        /// </summary>
        public static User GetCurrUser()
        {
            var acc = new CastleAccess();
            try
            {
                return acc.GetUser(CurrUserId);
            }
            finally
            {
                acc.CloseSession();
            }
        }

        /// <summary>
        /// 根據上下文成員名稱，返回對應內容
        /// </summary>
        /// <remarks>
        /// 由於threadCache或HttpContext中的緩衝物件都會在構造過程中創建
        /// 因此，這裏沒有對cache==null的判斷
        /// </remarks>
        /// <param name="name"></param>
        /// <returns></returns>
        public virtual object this[string name]
        {
            get
            {
                if (string.IsNullOrEmpty(name)) return null;
                NameBasedDictionary cache = GetCache();
                if (cache.Count <= 0) return null;
                object result;
                if (cache.TryGetValue(name, out result))
                    return result;
                return null;
            }
            set
            {
                if (string.IsNullOrEmpty(name)) return;
                NameBasedDictionary cache = GetCache();
                object temp;
                if (cache.TryGetValue(name, out temp))
                    cache[name] = value;
                else
                    cache.Add(name, value);
            }
        }

        /// <summary>
        /// 根據應用類型獲取相應上下文緩衝物件
        /// </summary>
        /// <returns>緩衝物件</returns>
        private static NameBasedDictionary GetCache()
        {
            NameBasedDictionary cache;
            if (m_IsWeb)
                cache = (NameBasedDictionary)HttpContext.Current.Items[ContextKey];
            else
                cache = _threadCache;

            if (cache == null)
                cache = new NameBasedDictionary();
            if (m_IsWeb)
                HttpContext.Current.Items[ContextKey] = cache;
            else
                _threadCache = cache;
            return cache;
        }

     

        /// <summary>
        /// 判斷當前應用是否為Web應用的Helper方法（非官方方法）
        /// </summary>
        /// <returns></returns>
        private static bool CheckWhetherIsWeb()
        {
            bool result = false;
            AppDomain domain = AppDomain.CurrentDomain;
            try
            {
                if (domain.ShadowCopyFiles)
                    result = (true);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            return result;
        }

        public static void ClareLoginCurrUserInfo()
        {
            CurrUserCode = "";
            CurrUserId = Guid.Empty;
            CurrUserName = "";
            UserRolesString = "";
        }

        public static bool CheckCurrUserIsAdmin()
        {
            return (UserRolesString.ToLower().IndexOf("admin") > -1);
        }

        #region Nested type: NameBasedDictionary

        /// <summary>
        /// 由於內部操作上，所有的容器類型均為Dictionary<string, object>
        /// 所以定義一個固定的類型名稱
        /// </summary>
        private class NameBasedDictionary : Dictionary<string, object>
        {
        }

        #endregion
    }
}
